import pytest
import asyncio
from src.core.knowledge_processor import KnowledgeProcessor
from src.database.manager import DatabaseManager
from unittest.mock import Mock, AsyncMock, patch
import uuid

@pytest.mark.asyncio
async def test_upload_and_search():
    # Mock DatabaseManager with necessary attributes
    mock_db_manager = Mock(spec=DatabaseManager)
    mock_db_manager.mongodb_client = Mock()
    mock_db_manager.mongodb_client.store_document = AsyncMock(return_value=None)
    mock_db_manager.mongodb_client.update_document = AsyncMock(return_value=None)
    mock_db_manager.chromadb_client = Mock()
    mock_db_manager.chromadb_client.store_document = AsyncMock(return_value=None)
    mock_db_manager.neo4j_client = Mock()
    mock_db_manager.neo4j_client.create_concept_node = AsyncMock(return_value=None)
    mock_db_manager.neo4j_client.create_relationship = AsyncMock(return_value=None)
    mock_db_manager.neo4j_client.find_related_knowledge = AsyncMock(return_value=[])
    
    config = {'knowledge': {'chunk_size': 1000, 'chunk_overlap': 200}}
    processor = KnowledgeProcessor(mock_db_manager, config)
    processor.is_initialized = True  # Simulate initialization
    
    # Mock internal components with AsyncMock where appropriate
    processor.document_processor = Mock()
    processor.document_processor.process_document = AsyncMock(return_value={'title': 'Test Document', 'content': 'This is a test document for retrieval.'})
    processor.text_splitter = Mock()
    processor.text_splitter.split_text = AsyncMock(return_value=['This is a test document for retrieval.'])
    processor.vectorizer = Mock()
    processor.vectorizer.vectorize = AsyncMock(return_value=[([0.1]*384, 'chunk_id')])
    processor.knowledge_graph_builder = Mock()
    processor.knowledge_graph_builder.extract_concepts = AsyncMock(return_value=[{'id': 'concept1', 'name': 'test', 'description': 'test concept'}])
    
    # Test data
    title = 'Test Document'
    content = 'This is a test document for retrieval.'
    user_id = 'test_user'
    
    # Upload document
    upload_result = await processor.upload_document(content, title, user_id)
    document_id = upload_result['document_id']
    
    # Mock search to return the uploaded document
    with patch.object(processor, 'search_knowledge', new_callable=AsyncMock) as mock_search:
        mock_search.return_value = [{'document_id': document_id, 'title': title, 'content': content, 'similarity': 0.9}]
        results = await processor.search_knowledge('test document', user_id, limit=1)
    
    assert len(results) > 0, 'No results found after upload'
    assert results[0]['title'] == title, 'Retrieved document does not match uploaded title'